`include "./AdamRiscv/define.vh"

module ctrl(   
    input  wire[2:0]    inst_fun,
    input  wire[6:0]    inst_op,
    output wire         br,
    output wire         mem_read,
    output wire         mem2reg,
    output wire[2:0]    alu_op,
    output wire         mem_write,
    output wire[1:0]    alu_src1,
    output wire[1:0]    alu_src2,
    output wire         br_addr_mode,
    output wire         regs_write,
    output wire         m_write
);

// alu_op M矩阵指令需要ADD操作，立即数与寄存器内地址相加 得访存地址
assign alu_op = (inst_op == `ItypeL || inst_op == `Stype || inst_op == `UtypeL || inst_op == `UtypeU)? 3'b000 :
(inst_op == 7'b0001011 && inst_fun != 3'b100)? 3'b000 :
(inst_op == 7'b0001011 && inst_fun == 3'b100)? 3'b101 :
(inst_op == `Btype)? 3'b001:
(inst_op == `Rtype)? 3'b010:
(inst_op == `ItypeA) ? 3'b011:
(inst_op == `ItypeJ || inst_op == `Jtype)? 3'b100 : 3'b111;
// alu_src1 第一操作数是reg， alu_src2 第二操作数是IMM
assign alu_src1 = (inst_op == `ItypeJ || inst_op == `Jtype || inst_op == `UtypeU) ? `PC :
(inst_op == `UtypeL) ? `NULL :
(inst_op == 7'b0001011 && inst_fun == 3'b011) ? `MOVE : `REG;
assign alu_src2 = (inst_op == `ItypeL || inst_op == `Stype || inst_op == `UtypeU || inst_op == `ItypeA || inst_op == `UtypeL )? `IMM :
(inst_op == 7'b0001011 && (inst_fun == 3'b000 || inst_fun == 3'b001)) ? `IMM :
(inst_op == 7'b0001011 && (inst_fun == 3'b010 || inst_fun == 3'b011)) ? `ZERO :
(inst_op == `ItypeJ || inst_op == `Jtype) ? `PC_PLUS4 : `REG;
assign br_addr_mode = (inst_op == `ItypeJ)? `J_REG : `B_PC;


assign br = (inst_op == `Btype || inst_op == `ItypeJ || inst_op == `Jtype)? 1:0;
// M matrix 需要额外处理
assign mem_write = ( inst_op == `Stype || (inst_op == 7'b0001011 && inst_fun == 3'b001))? 1:0;
assign mem_read = ( inst_op == `ItypeL || (inst_op == 7'b0001011 && inst_fun == 3'b000))? 1:0;
assign regs_write = (inst_op == `ItypeL || inst_op == `Rtype || inst_op == `UtypeU || inst_op == `ItypeA || inst_op == `ItypeJ || inst_op == `UtypeL || inst_op == `Jtype || (inst_op == 7'b0001011 && (inst_fun == 3'b001 || inst_fun == 3'b011)))? 1:0;
assign m_write = (inst_op == 7'b0001011 && (inst_fun == 3'b000 || inst_fun == 3'b010))? 1:0;
//assign regs_write = (inst_op == `Stype || inst_op == `Btype)? 0:1; // when the inst is beyond the definition ,like 0x00000000, reg_write is 0
assign mem2reg = ((regs_write || m_write) && (inst_op == `ItypeL || (inst_op == 7'b0001011 && inst_fun == 3'b000)))?1:0;

endmodule
